package com.atguigu.gmall.item.controller;

import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.util.UUID;

/**
 * ClassName: RedissonController
 * Package: com.atguigu.gmall.item.controller
 * Description:
 *
 * @Author ltystart
 * @Create 2025/8/28 15:33
 * @Version 1.0
 */
@RestController
public class RedissonController {
    @Autowired
    private RedissonClient redissonClient;


    String val = "okkkkkkkkkkkkkk";


    /**
     * 限流：  2000/s
     */
    @GetMapping("/req")
    public String req() throws InterruptedException {
        RSemaphore semaphore = redissonClient.getSemaphore("xa-tcc");
        boolean acquire = semaphore.tryAcquire(); //
        if(acquire){
            //执行业务......
            Thread.sleep(30000);
            semaphore.release();
            return "业务执行完成...";
        }else {
            return "当前流量过大，请稍后";
        }
    }




    @PostConstruct
    public void tcc(){
        RSemaphore semaphore = redissonClient.getSemaphore("xa-tcc");
        semaphore.trySetPermits(3);

    }

    /**
     * CountDownLatch  只减不增
     * Semaphore  能减能增
     *
     * 停车场 5个车位
     * @return
     */
    @GetMapping("/tcc/status")
    public String tcc111(){
        RSemaphore semaphore = redissonClient.getSemaphore("xa-tcc");

        return "停车场初始化完成：剩余车位："+semaphore.availablePermits();
    }

    /**
     * 停一个车
     * @return
     * @throws InterruptedException
     */
    @GetMapping("/tcc/park")
    public String tc() throws InterruptedException {
        RSemaphore semaphore = redissonClient.getSemaphore("xa-tcc");

        semaphore.acquire();
        return "停车成功";
    }


    /**
     * 停一个车
     * @return
     * @throws InterruptedException
     */
    @GetMapping("/tcc/go")
    public String tcgo() throws InterruptedException {
        RSemaphore semaphore = redissonClient.getSemaphore("xa-tcc");

        semaphore.release(); //释放一个信号
        return "车开走了~~~";
    }


    @GetMapping("/readlock")
    public String readV() throws InterruptedException {
        //1、创建读写锁
        RReadWriteLock lock = redissonClient.getReadWriteLock("val-lock");

        //2、得到读锁
        RLock readLock = lock.readLock();
        try {
            readLock.lock();
            System.out.println(Thread.currentThread()+"读锁加锁成功");
            Thread.sleep(10000);
            return val;
        }finally {
            System.out.println(Thread.currentThread()+"读锁解锁成功");
            readLock.unlock();
        }
    }

    @GetMapping("/writelock")
    public String writeV() throws InterruptedException {
        //1、创建读写锁
        RReadWriteLock lock = redissonClient.getReadWriteLock("val-lock");

        //2、得到写锁
        RLock writeLock = lock.writeLock();
        try {
            writeLock.lock();
            System.out.println(Thread.currentThread()+"写锁加锁成功");
            Thread.sleep(10000);
            val = UUID.randomUUID().toString();
            return val;
        }finally {
            System.out.println(Thread.currentThread()+"写锁解锁成功");
            writeLock.unlock();
        }
    }



    @GetMapping("/lock")
    public String ReentrantLock() throws InterruptedException {
//        RLock fairLock = redisson.getFairLock("lock");
        //1、得到锁对象
        RLock lock = redissonClient.getLock("lock");

        //2、加锁
        lock.lock(); //阻塞式等锁，一定等到锁
//        boolean b = lock.tryLock();
//        boolean b = lock.tryLock(); //尝试得一下锁。
        //waitTime：等待时间； 最多等多久
        //leaseTime：释放时间；锁自动在25秒以后释放
        //thread.setDaemon();
        //

        try {
            System.out.println(Thread.currentThread() + "得到锁");
            Thread.sleep(20000);
            //一定是可重入锁
            lock.lock();
            System.out.println("重入锁获取成功");
            Thread.sleep(10000);
            int i = 10 / 0;

        } finally {
            //一定保证解锁：
            //1、业务异常，finally一定执行解锁了
            //2、业务断电，续期线程不运行了，30s倒计时一到自动解锁
            //加锁的时候，不要指定锁的释放时间，就会拥有自动续期功能。
            System.out.println(Thread.currentThread() + "释放锁");
            lock.unlock(); //redisson在解锁的时候也会判断是否自己的锁
            //加解锁成对出现
            lock.unlock();
        }

        //由于每个请求进来，Tomcat会分配一个线程进行处理，处理完成以后线程回收放到线程池。
        //redisson续期的时候，设置的是续期线程是这个请求处理线程的守护线程。redisson没做好这个判断，
        //导致守护线程一直在续期
//        int i = 10/0;
//        lock.tryLock(10,25, TimeUnit.SECONDS);
//        if (b) {
//            System.out.println(Thread.currentThread() + "得到锁");
//
//            //执行业务
//            //Thread.sleep(7000); //redisson不能正确处理sleep
//
//            int i = 10 / 0;
//            //给自动续期了？续期bug？
//
//            //3、解锁
//            System.out.println(Thread.currentThread() + "释放锁");
//            lock.unlock();
//        } else {
//
//        }

        return "ok";

    }
//    @GetMapping("/lock")
//    public String ReentrantLock() throws InterruptedException {
//        //1.得到锁对象
//        RLock lock = redissonClient.getLock("lock");
//
//        //2.加锁
//        lock.lock();//阻塞式等锁，一定要等到锁
//        System.out.println(Thread.currentThread()+"加锁成功");
//
//        //执行业务
//        //redisson不能正确处理sleep
//        Thread.sleep(5000);
//
//        int i = 10/0;
//
//        //3.解锁
//        System.out.println(Thread.currentThread()+"解锁成功");
//        lock.unlock();
//
//        return "ok";
//    }
}
